import os from 'os';

const getIPAddress = () => {
	let interfaces = os.networkInterfaces();
	let family = 'ipv4';
	let method = ''; // 'private', 'public' or ''

	const isLoopback = (addr) => {
		return (
			/^(::f{4}:)?127\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/.test(addr) ||
			/^fe80::1$/.test(addr) ||
			/^::1$/.test(addr) ||
			/^::$/.test(addr)
		);
	};
	const loopback = (family) => {
		family = family ? family.toLowerCase() : 'ipv4';
		if (family !== 'ipv4' && family !== 'ipv6') throw new Error('family must be ipv4 or ipv6');
		return family === 'ipv4' ? '127.0.0.1' : 'fe80::1';
	};
	const isPrivate = (addr) => {
		return (
			/^(::f{4}:)?10\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(addr) ||
			/^(::f{4}:)?192\.168\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(addr) ||
			/^(::f{4}:)?172\.(1[6-9]|2\d|30|31)\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(addr) ||
			/^(::f{4}:)?127\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(addr) ||
			/^(::f{4}:)?169\.254\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(addr) ||
			/^f[cd][0-9a-f]{2}:/i.test(addr) ||
			/^fe80:/i.test(addr) ||
			/^::1$/.test(addr) ||
			/^::$/.test(addr)
		);
	};

	if (method && method !== 'private' && method !== 'public') {
		const res = interfaces[method].filter((details) => {
			const itemFamily = details.family.toLowerCase();
			return itemFamily === family;
		});
		if (res.length === 0) return undefined;
		return res[0].address;
	}
	const all = Object.keys(interfaces)
		.map((nic) => {
			const addresses = interfaces[nic].filter((details) => {
				details.family = details.family.toLowerCase();
				if (details.family !== family || isLoopback(details.address)) {
					return false;
				} else if (!method) {
					return true;
				}
				return method === 'public' ? isPrivate(details.address) : !isPrivate(details.address);
			});
			return addresses.length ? addresses[0].address : undefined;
		})
		.filter(Boolean);

	const host = !all.length ? loopback(family) : all[0];

	// console.log('////////////////////');
	// console.log(all);
	// console.log('////////////////////');
	return host;
};

export default getIPAddress;
